#include "nemu.h"
#include "monitor/monitor.h"
#include "monitor/expr.h"
#include "monitor/watchpoint.h"
extern WP** get_static_head();
// extern jmp_buf jmpbuf;
/* The assembly code of instructions executed is only output to the screen
 * when the number of instructions executed is less than this value.
 * This is useful when you use the `si' command.
 * You can modify this value as you want.
 */
#define MAX_INSTR_TO_PRINT 10

int nemu_state = NEMU_STOP;

void exec_wrapper(bool);
int point[32];
/* Simulate how the CPU works. */
void cpu_exec(uint64_t n) {
  if (nemu_state == NEMU_END) {
    printf("Program execution has ended. To restart the program, exit NEMU and run again.\n");
    return;
  }
  nemu_state = NEMU_RUNNING;

  bool print_flag = n < MAX_INSTR_TO_PRINT;

  for (; n > 0; n --) {
    /* Execute one instruction, including instruction fetch,
     * instruction decode, and the actual execution. */
    exec_wrapper(print_flag);

#ifdef DEBUG
    /* TODO: check watchpoints here. */
  WP** head = get_static_head();
  WP* temp = *head;
  bool warning = false;
  int num = 0;
  while(temp != NULL){
    bool *success;
    uint32_t expr_value = expr(temp->expr,success);
    if(temp->value != expr_value){
      warning = true;
      point[num] = temp->NO;
      num += 1;
      temp->value = expr_value;
    }
    temp = temp->next;
  }
  if(warning){
    for(int i=0;i<num;i++){
      printf("the watchpoint id:%d\tstriked! see more by: info w\n", point[i]);
      point[i] = -1;
    }
    warning = false;
    // break up to mainloop
    nemu_state = NEMU_STOP;
  }
#endif

#ifdef HAS_IOE
    extern void device_update();
    device_update();
#endif

    if (nemu_state != NEMU_RUNNING) { return; }
  }

  if (nemu_state == NEMU_RUNNING) { nemu_state = NEMU_STOP; }
}
